package com.nebula.seckill.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;

/**
 * @Author: llq
 * @Date: 2019/9/24
 */
@Slf4j
public class MsService {

    /***
     * 抢购代码
     * 对抢购代码加redis分布式锁,即在同一时刻,只有一个客户持有锁去购买
     * 拿到锁后减库存,付款.....
     * 释放锁,让别人去抢购
     * @param redisTemplate
     * @param key 锁的key是固定的
     * pronum 库存的数量
     * @return
     * @throws InterruptedException
     */
    public boolean seckill(RedisTemplate<String,Object> redisTemplate, String key) throws Exception {
        RedisLock lock = new RedisLock(redisTemplate, key, 10000, 20000);
        try {
            // 开启锁
            // 判断当前锁是否被调用，被调用就拿不到锁，是否可以抢购
            if (lock.lock()) {
                // 需要加锁的代码，下面的代码只有一个线程可以进行

                //下单支付
                //下单了，不一定会支付，等抢购时间过去，将未支付的抢购订单通过消息中间件的延迟队列设置时间，变为订单关闭

                //减库存
                //根据key获取到商品数量redisTenplate.obsforvalue.get(key)
                String pronum=lock.get("pronum");
                //修改库存，这里是将数量存入redis
                //购买了.减库存数量1（1是指购买数量）,剩余库存数量要>=0,不然就证明抢光了
                if(Integer.parseInt(pronum)-1>=0) {
                    lock.set("pronum",String.valueOf(Integer.parseInt(pronum)-1));
                    //Thread.currentThread().getName()  当前线程引用的名字
                    log.info("剩余库存数量:"+(Integer.parseInt(pronum)-1)+"购买成功!!!"+"当前线程是"+Thread.currentThread().getName());
                }else {
                    log.info("已经被抢光了，请参与下轮抢购");
                }
                log.info("++++++++++++++++++++++++++++++++++++++参加了抢购");
                return true;
            }


        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // 为了让分布式锁的算法更稳键些，持有锁的客户端在解锁之前应该再检查一次自己的锁是否已经超时，
            // 再去做DEL操作，因为可能客户端因为某个耗时的操作而挂起，
            // 操作完的时候锁因为超时已经被别人获得，这时就不必解锁了。 ————这里没有做
            lock.unlock();
        }
        return false;
    }

}
